{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "39fd1948-b5c3-48c4-b10e-2ae7e8c83334",
   "metadata": {},
   "source": [
    "# Basic Multi-agent Collaboration\n",
    "\n",
    "A single agent can usually operate effectively using a handful of tools within a single domain, but even using powerful models like `gpt-4`, it can be less effective at using many tools. \n",
    "\n",
    "One way to approach complicated tasks is through a \"divide-and-conquer\" approach: create an specialized agent for each task or domain and route tasks to the correct \"expert\".\n",
    "\n",
    "This notebook (inspired by the paper [AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation](https://arxiv.org/abs/2308.08155), by Wu, et. al.) shows one way to do this using LangGraph.\n",
    "\n",
    "The resulting graph will look something like the following diagram:\n",
    "\n",
    "![multi_agent diagram](./img/simple_multi_agent_diagram.png)\n",
    "\n",
    "Before we get started, a quick note: this and other multi-agent notebooks are designed to show _how_ you can implement certain design patterns in LangGraph. If the pattern suits your needs, we recommend combining it with some of the other fundamental patterns described elsewhere in the docs for best performance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "0d7b6dcc-c985-46e2-8457-7e6b0298b950",
   "metadata": {},
   "outputs": [],
   "source": [
    "# %%capture --no-stderr\n",
    "# %pip install -U langchain langchain_openai langsmith pandas langchain_experimental matplotlib langgraph langchain_core"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "743c19df-6da9-4d1e-b2d2-ea40080b9fdc",
   "metadata": {},
   "outputs": [],
   "source": [
    "import getpass\n",
    "import os\n",
    "from dotenv import load_dotenv; load_dotenv()\n",
    "\n",
    "\n",
    "def _set_if_undefined(var: str):\n",
    "    if not os.environ.get(var):\n",
    "        os.environ[var] = getpass.getpass(f\"Please provide your {var}\")\n",
    "\n",
    "\n",
    "_set_if_undefined(\"OPENAI_API_KEY\")\n",
    "_set_if_undefined(\"OPENAI_API_BASE\")\n",
    "_set_if_undefined(\"LANGCHAIN_API_KEY\")\n",
    "_set_if_undefined(\"TAVILY_API_KEY\")\n",
    "\n",
    "# Optional, add tracing in LangSmith\n",
    "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
    "os.environ[\"LANGCHAIN_PROJECT\"] = \"Multi-agent Collaboration\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e4344a7-21df-4d54-90d2-9d19b3416ffb",
   "metadata": {},
   "source": [
    "## Create Agents\n",
    "\n",
    "The following helper functions will help create agents. These agents will then be nodes in the graph.\n",
    "\n",
    "You can skip ahead if you just want to see what the graph looks like."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "4325a10e-38dc-4a98-9004-e1525eaba377",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.messages import (\n",
    "    BaseMessage,\n",
    "    HumanMessage,\n",
    "    ToolMessage,\n",
    ")\n",
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "\n",
    "from langgraph.graph import END, StateGraph, START\n",
    "\n",
    "\n",
    "def create_agent(llm, tools, system_message: str):\n",
    "    \"\"\"Create an agent.\"\"\"\n",
    "    prompt = ChatPromptTemplate.from_messages(\n",
    "        [\n",
    "            (\n",
    "                \"system\",\n",
    "                \"You are a helpful AI assistant, collaborating with other assistants.\"\n",
    "                \" Use the provided tools to progress towards answering the question.\"\n",
    "                \" If you are unable to fully answer, that's OK, another assistant with different tools \"\n",
    "                \" will help where you left off. Execute what you can to make progress.\"\n",
    "                \" If you or any of the other assistants have the final answer or deliverable,\"\n",
    "                \" prefix your response with FINAL ANSWER so the team knows to stop.\"\n",
    "                \" You have access to the following tools: {tool_names}.\\n{system_message}\",\n",
    "            ),\n",
    "            MessagesPlaceholder(variable_name=\"messages\"),\n",
    "        ]\n",
    "    )\n",
    "    prompt = prompt.partial(system_message=system_message)\n",
    "    prompt = prompt.partial(tool_names=\", \".join([tool.name for tool in tools]))\n",
    "    return prompt | llm.bind_tools(tools)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4b40de2-5dd4-4d5b-882e-577210723ff4",
   "metadata": {},
   "source": [
    "## Define tools\n",
    "\n",
    "We will also define some tools that our agents will use in the future"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "ca076f3b-a729-4ca9-8f91-05c2ba58d610",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Annotated\n",
    "\n",
    "from langchain_community.tools.tavily_search import TavilySearchResults\n",
    "from langchain_core.tools import tool\n",
    "from langchain_experimental.utilities import PythonREPL\n",
    "\n",
    "tavily_tool = TavilySearchResults(max_results=5)\n",
    "\n",
    "# Warning: This executes code locally, which can be unsafe when not sandboxed\n",
    "\n",
    "repl = PythonREPL()\n",
    "\n",
    "\n",
    "@tool\n",
    "def python_repl(\n",
    "    code: Annotated[str, \"The python code to execute to generate your chart.\"],\n",
    "):\n",
    "    \"\"\"Use this to execute python code. If you want to see the output of a value,\n",
    "    you should print it out with `print(...)`. This is visible to the user.\"\"\"\n",
    "    try:\n",
    "        result = repl.run(code)\n",
    "    except BaseException as e:\n",
    "        return f\"Failed to execute. Error: {repr(e)}\"\n",
    "    result_str = f\"Successfully executed:\\n```python\\n{code}\\n```\\nStdout: {result}\"\n",
    "    return (\n",
    "        result_str + \"\\n\\nIf you have completed all tasks, respond with FINAL ANSWER.\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1b54c0c-0b09-408b-abc5-86308929afb6",
   "metadata": {},
   "source": [
    "## Create graph\n",
    "\n",
    "Now that we've defined our tools and made some helper functions, will create the individual agents below and tell them how to talk to each other using LangGraph."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c6a8c3c-86a0-46aa-b970-ab070fb787d9",
   "metadata": {},
   "source": [
    "### Define State\n",
    "\n",
    "We first define the state of the graph. This will just a list of messages, along with a key to track the most recent sender"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "290c91d4-f6f4-443c-8181-233d39102974",
   "metadata": {},
   "outputs": [],
   "source": [
    "import operator\n",
    "from typing import Annotated, Sequence, TypedDict\n",
    "\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "\n",
    "# This defines the object that is passed between each node\n",
    "# in the graph. We will create different nodes for each agent and tool\n",
    "class AgentState(TypedDict):\n",
    "    messages: Annotated[Sequence[BaseMessage], operator.add]\n",
    "    sender: str"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "911a283e-ea04-40c1-b792-f9e5f7d81203",
   "metadata": {},
   "source": [
    "### Define Agent Nodes\n",
    "\n",
    "We now need to define the nodes. First, let's define the nodes for the agents."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "71b790ca-9cef-4b22-b469-4b1d5d8424d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import functools\n",
    "\n",
    "from langchain_core.messages import AIMessage\n",
    "\n",
    "\n",
    "# Helper function to create a node for a given agent\n",
    "def agent_node(state, agent, name):\n",
    "    result = agent.invoke(state)\n",
    "    # We convert the agent output into a format that is suitable to append to the global state\n",
    "    if isinstance(result, ToolMessage):\n",
    "        pass\n",
    "    else:\n",
    "        result = AIMessage(**result.dict(exclude={\"type\", \"name\"}), name=name)\n",
    "    return {\n",
    "        \"messages\": [result],\n",
    "        # Since we have a strict workflow, we can\n",
    "        # track the sender so we know who to pass to next.\n",
    "        \"sender\": name,\n",
    "    }\n",
    "\n",
    "\n",
    "# llm = ChatOpenAI(model=\"gpt-4o-mini\")\n",
    "# llm = ChatOpenAI(model=\"qwen2:72b\", api_key=\"\", base_url=\"http://generate.yangzhiqiang.tech/v1\")\n",
    "llm = ChatOpenAI(model=\"Baichuan2\", api_key=\"123\", base_url=\"http://bc.192.168.107.2.nip.io/v1\")\n",
    "# llm = ChatOpenAI(model=\"deepseek-chat\", api_key=\"sk-08a600a05b724252ae7c1320812447eb\", base_url=\"https://api.deepseek.com\")\n",
    "# 豆包, Doubao-pro-4k\n",
    "# llm = ChatOpenAI(model=\"ep-20240801230159-vp5jn\", api_key=\"eb64ed3f-f257-46d1-a046-c28cb553ca28\", base_url=\"https://ark.cn-beijing.volces.com/api/v3\")\n",
    "\n",
    "# 导入与 Baichuan 语言模型交互的模块。\n",
    "# from langchain_community.chat_models.baichuan import ChatBaichuan\n",
    "# 初始化 Baichuan 模型。\n",
    "# llm = ChatBaichuan(temperature=0, model=\"Baichuan2\", baichuan_api_key=\"123\", baichuan_api_base=\"http://bc.192.168.107.2.nip.io/v1/chat/completions\")\n",
    "\n",
    "# 导入与 Tongyi 语言模型交互的模块。\n",
    "# from langchain_community.chat_models.tongyi import ChatTongyi\n",
    "# 初始化 Tongyi 模型\n",
    "# llm = ChatTongyi(temperature=0, seed=1234, model=\"qwen2:72b\", dashscope_api_key=\"\", dashscope_api_base=\"http://generate.yangzhiqiang.tech/v1/chat/completions\")\n",
    "\n",
    "# Research agent and node\n",
    "research_agent = create_agent(\n",
    "    llm,\n",
    "    [tavily_tool],\n",
    "    system_message=\"You should provide accurate data for the chart_generator to use.\",\n",
    ")\n",
    "research_node = functools.partial(agent_node, agent=research_agent, name=\"Researcher\")\n",
    "\n",
    "# chart_generator\n",
    "chart_agent = create_agent(\n",
    "    llm,\n",
    "    [python_repl],\n",
    "    system_message=\"Any charts you display will be visible by the user.\",\n",
    ")\n",
    "chart_node = functools.partial(agent_node, agent=chart_agent, name=\"chart_generator\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71c7f1b2-24a3-4340-bcb2-feb22e344fb6",
   "metadata": {},
   "source": [
    "### Define Tool Node\n",
    "\n",
    "We now define a node to run the tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "d9a79c76-5c7c-42f6-91cf-635bc8305804",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph.prebuilt import ToolNode\n",
    "\n",
    "tools = [tavily_tool, python_repl]\n",
    "tool_node = ToolNode(tools)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcb30498-dbc4-4b20-980f-da08ebc9da56",
   "metadata": {},
   "source": [
    "### Define Edge Logic\n",
    "\n",
    "We can define some of the edge logic that is needed to decide what to do based on results of the agents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "4f4b4d37-e8a3-4abb-8d42-eaea26016f35",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Either agent can decide to end\n",
    "from typing import Literal\n",
    "\n",
    "\n",
    "def router(state) -> Literal[\"call_tool\", \"__end__\", \"continue\"]:\n",
    "    # This is the router\n",
    "    messages = state[\"messages\"]\n",
    "    last_message = messages[-1]\n",
    "    if last_message.tool_calls:\n",
    "        # The previous agent is invoking a tool\n",
    "        return \"call_tool\"\n",
    "    if \"FINAL ANSWER\" in last_message.content:\n",
    "        # Any agent decided the work is done\n",
    "        return \"__end__\"\n",
    "    return \"continue\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9359c34-e191-43a2-a3d4-f2dea636dfd2",
   "metadata": {},
   "source": [
    "### Define the Graph\n",
    "\n",
    "We can now put it all together and define the graph!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "4dce3901-6ad5-4df5-8528-6e865cf96cb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow = StateGraph(AgentState)\n",
    "\n",
    "workflow.add_node(\"Researcher\", research_node)\n",
    "workflow.add_node(\"chart_generator\", chart_node)\n",
    "workflow.add_node(\"call_tool\", tool_node)\n",
    "\n",
    "workflow.add_conditional_edges(\n",
    "    \"Researcher\",\n",
    "    router,\n",
    "    {\"continue\": \"chart_generator\", \"call_tool\": \"call_tool\", \"__end__\": END},\n",
    ")\n",
    "workflow.add_conditional_edges(\n",
    "    \"chart_generator\",\n",
    "    router,\n",
    "    {\"continue\": \"Researcher\", \"call_tool\": \"call_tool\", \"__end__\": END},\n",
    ")\n",
    "\n",
    "workflow.add_conditional_edges(\n",
    "    \"call_tool\",\n",
    "    # Each agent node updates the 'sender' field\n",
    "    # the tool calling node does not, meaning\n",
    "    # this edge will route back to the original agent\n",
    "    # who invoked the tool\n",
    "    lambda x: x[\"sender\"],\n",
    "    {\n",
    "        \"Researcher\": \"Researcher\",\n",
    "        \"chart_generator\": \"chart_generator\",\n",
    "    },\n",
    ")\n",
    "workflow.add_edge(START, \"Researcher\")\n",
    "graph = workflow.compile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "97f8e0eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "try:\n",
    "    display(Image(graph.get_graph(xray=True).draw_mermaid_png()))\n",
    "except Exception:\n",
    "    # This requires some extra dependencies and is optional\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c9447e7-9ab6-43eb-8ae6-9b52f8ba8425",
   "metadata": {},
   "source": [
    "## Invoke\n",
    "\n",
    "With the graph created, you can invoke it! Let's have it chart some stats for us."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "176a99b0-b457-45cf-8901-90facaa852da",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Researcher': {'messages': [AIMessage(content='I can\\'t draw a graph for you here, but I can help you fetch the data and write a script to plot the graph. You can use the pandas and matplotlib libraries to plot the graph. Here\\'s a sample script:\\n\\n```python\\nimport pandas as pd\\nimport matplotlib.pyplot as plt\\n\\n# Fetch the GDP data from a URL\\nurl = \"https://www.ons.gov.uk/economy/grossdomesticproductuk/timeseries/abmiqnjf/qna\"\\ndata = pd.read_csv(url)\\n\\n# Select the last 5 years of data\\nrecent_data = data[-5:]\\n\\n# Plot the line graph\\nplt.plot(recent_data[\\'Time\\'], recent_data[\\'GDP\\'])\\nplt.xlabel(\\'Years\\')\\nplt.ylabel(\\'GDP\\')\\nplt.title(\\'UK GDP Over the Past 5 Years\\')\\nplt.show()\\n```\\n\\nYou can run this script in a Python environment like Jupyter Notebook or Google Colab. This script will fetch the latest 5 years of UK GDP data from the ONS website and plot a line graph using matplotlib. You can customize the graph further by adding labels, changing the axis range, etc.', response_metadata={'token_usage': {'completion_tokens': 287, 'prompt_tokens': 32, 'total_tokens': 319}, 'model_name': 'Baichuan2-53B', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, name='Researcher', id='run-52342117-0f32-4b24-87cc-c82f01c22b3d-0', usage_metadata={'input_tokens': 32, 'output_tokens': 287, 'total_tokens': 319})], 'sender': 'Researcher'}}\n",
      "----\n"
     ]
    },
    {
     "ename": "BadRequestError",
     "evalue": "Error code: 400 - {'error': {'code': None, 'param': 'messages.[2].role', 'type': 'invalid_request_error', 'message': 'The role in the latest message must be `user` or `tool` - `assistant`'}}",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mBadRequestError\u001b[0m                           Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[56], line 14\u001b[0m\n\u001b[0;32m      1\u001b[0m events \u001b[38;5;241m=\u001b[39m graph\u001b[38;5;241m.\u001b[39mstream(\n\u001b[0;32m      2\u001b[0m     {\n\u001b[0;32m      3\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessages\u001b[39m\u001b[38;5;124m\"\u001b[39m: [\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m     12\u001b[0m     {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrecursion_limit\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;241m150\u001b[39m},\n\u001b[0;32m     13\u001b[0m )\n\u001b[1;32m---> 14\u001b[0m \u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43ms\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mevents\u001b[49m\u001b[43m:\u001b[49m\n\u001b[0;32m     15\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mprint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     16\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mprint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m----\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langgraph\\pregel\\__init__.py:966\u001b[0m, in \u001b[0;36mPregel.stream\u001b[1;34m(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug)\u001b[0m\n\u001b[0;32m    963\u001b[0m         \u001b[38;5;28;01mdel\u001b[39;00m fut, task\n\u001b[0;32m    965\u001b[0m \u001b[38;5;66;03m# panic on failure or timeout\u001b[39;00m\n\u001b[1;32m--> 966\u001b[0m \u001b[43m_panic_or_proceed\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdone\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minflight\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mloop\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstep\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    967\u001b[0m \u001b[38;5;66;03m# don't keep futures around in memory longer than needed\u001b[39;00m\n\u001b[0;32m    968\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m done, inflight, futures\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langgraph\\pregel\\__init__.py:1367\u001b[0m, in \u001b[0;36m_panic_or_proceed\u001b[1;34m(done, inflight, step, timeout_exc_cls)\u001b[0m\n\u001b[0;32m   1365\u001b[0m             inflight\u001b[38;5;241m.\u001b[39mpop()\u001b[38;5;241m.\u001b[39mcancel()\n\u001b[0;32m   1366\u001b[0m         \u001b[38;5;66;03m# raise the exception\u001b[39;00m\n\u001b[1;32m-> 1367\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[0;32m   1369\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m inflight:\n\u001b[0;32m   1370\u001b[0m     \u001b[38;5;66;03m# if we got here means we timed out\u001b[39;00m\n\u001b[0;32m   1371\u001b[0m     \u001b[38;5;28;01mwhile\u001b[39;00m inflight:\n\u001b[0;32m   1372\u001b[0m         \u001b[38;5;66;03m# cancel all pending tasks\u001b[39;00m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langgraph\\pregel\\executor.py:60\u001b[0m, in \u001b[0;36mBackgroundExecutor.done\u001b[1;34m(self, task)\u001b[0m\n\u001b[0;32m     58\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdone\u001b[39m(\u001b[38;5;28mself\u001b[39m, task: concurrent\u001b[38;5;241m.\u001b[39mfutures\u001b[38;5;241m.\u001b[39mFuture) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m     59\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 60\u001b[0m         \u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresult\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     61\u001b[0m     \u001b[38;5;28;01mexcept\u001b[39;00m GraphInterrupt:\n\u001b[0;32m     62\u001b[0m         \u001b[38;5;66;03m# This exception is an interruption signal, not an error\u001b[39;00m\n\u001b[0;32m     63\u001b[0m         \u001b[38;5;66;03m# so we don't want to re-raise it on exit\u001b[39;00m\n\u001b[0;32m     64\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtasks\u001b[38;5;241m.\u001b[39mpop(task)\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\concurrent\\futures\\_base.py:449\u001b[0m, in \u001b[0;36mFuture.result\u001b[1;34m(self, timeout)\u001b[0m\n\u001b[0;32m    447\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m CancelledError()\n\u001b[0;32m    448\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_state \u001b[38;5;241m==\u001b[39m FINISHED:\n\u001b[1;32m--> 449\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__get_result\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    451\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_condition\u001b[38;5;241m.\u001b[39mwait(timeout)\n\u001b[0;32m    453\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_state \u001b[38;5;129;01min\u001b[39;00m [CANCELLED, CANCELLED_AND_NOTIFIED]:\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\concurrent\\futures\\_base.py:401\u001b[0m, in \u001b[0;36mFuture.__get_result\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    399\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception:\n\u001b[0;32m    400\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 401\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception\n\u001b[0;32m    402\u001b[0m     \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[0;32m    403\u001b[0m         \u001b[38;5;66;03m# Break a reference cycle with the exception in self._exception\u001b[39;00m\n\u001b[0;32m    404\u001b[0m         \u001b[38;5;28mself\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\concurrent\\futures\\thread.py:58\u001b[0m, in \u001b[0;36m_WorkItem.run\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m     55\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[0;32m     57\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 58\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     59\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[0;32m     60\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfuture\u001b[38;5;241m.\u001b[39mset_exception(exc)\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langgraph\\pregel\\retry.py:25\u001b[0m, in \u001b[0;36mrun_with_retry\u001b[1;34m(task, retry_policy)\u001b[0m\n\u001b[0;32m     23\u001b[0m task\u001b[38;5;241m.\u001b[39mwrites\u001b[38;5;241m.\u001b[39mclear()\n\u001b[0;32m     24\u001b[0m \u001b[38;5;66;03m# run the task\u001b[39;00m\n\u001b[1;32m---> 25\u001b[0m \u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mproc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minput\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     26\u001b[0m \u001b[38;5;66;03m# if successful, end\u001b[39;00m\n\u001b[0;32m     27\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\runnables\\base.py:2873\u001b[0m, in \u001b[0;36mRunnableSequence.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   2869\u001b[0m config \u001b[38;5;241m=\u001b[39m patch_config(\n\u001b[0;32m   2870\u001b[0m     config, callbacks\u001b[38;5;241m=\u001b[39mrun_manager\u001b[38;5;241m.\u001b[39mget_child(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mseq:step:\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mi\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m1\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m   2871\u001b[0m )\n\u001b[0;32m   2872\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m i \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m-> 2873\u001b[0m     \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[43mstep\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m   2874\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m   2875\u001b[0m     \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m step\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config)\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langgraph\\utils.py:102\u001b[0m, in \u001b[0;36mRunnableCallable.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    100\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m accepts_config(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunc):\n\u001b[0;32m    101\u001b[0m         kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mconfig\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m config\n\u001b[1;32m--> 102\u001b[0m     ret \u001b[38;5;241m=\u001b[39m \u001b[43mcontext\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    103\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(ret, Runnable) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrecurse:\n\u001b[0;32m    104\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m ret\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config)\n",
      "Cell \u001b[1;32mIn[50], line 8\u001b[0m, in \u001b[0;36magent_node\u001b[1;34m(state, agent, name)\u001b[0m\n\u001b[0;32m      7\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21magent_node\u001b[39m(state, agent, name):\n\u001b[1;32m----> 8\u001b[0m     result \u001b[38;5;241m=\u001b[39m \u001b[43magent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstate\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m      9\u001b[0m     \u001b[38;5;66;03m# We convert the agent output into a format that is suitable to append to the global state\u001b[39;00m\n\u001b[0;32m     10\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(result, ToolMessage):\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\runnables\\base.py:2875\u001b[0m, in \u001b[0;36mRunnableSequence.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   2873\u001b[0m             \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m step\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m   2874\u001b[0m         \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 2875\u001b[0m             \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[43mstep\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m   2876\u001b[0m \u001b[38;5;66;03m# finish the root run\u001b[39;00m\n\u001b[0;32m   2877\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\runnables\\base.py:5060\u001b[0m, in \u001b[0;36mRunnableBindingBase.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   5054\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21minvoke\u001b[39m(\n\u001b[0;32m   5055\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   5056\u001b[0m     \u001b[38;5;28minput\u001b[39m: Input,\n\u001b[0;32m   5057\u001b[0m     config: Optional[RunnableConfig] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   5058\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Optional[Any],\n\u001b[0;32m   5059\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Output:\n\u001b[1;32m-> 5060\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbound\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   5061\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m   5062\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_merge_configs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   5063\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m{\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   5064\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\language_models\\chat_models.py:274\u001b[0m, in \u001b[0;36mBaseChatModel.invoke\u001b[1;34m(self, input, config, stop, **kwargs)\u001b[0m\n\u001b[0;32m    263\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21minvoke\u001b[39m(\n\u001b[0;32m    264\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m    265\u001b[0m     \u001b[38;5;28minput\u001b[39m: LanguageModelInput,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    269\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any,\n\u001b[0;32m    270\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m BaseMessage:\n\u001b[0;32m    271\u001b[0m     config \u001b[38;5;241m=\u001b[39m ensure_config(config)\n\u001b[0;32m    272\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m cast(\n\u001b[0;32m    273\u001b[0m         ChatGeneration,\n\u001b[1;32m--> 274\u001b[0m         \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgenerate_prompt\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    275\u001b[0m \u001b[43m            \u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_convert_input\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    276\u001b[0m \u001b[43m            \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    277\u001b[0m \u001b[43m            \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcallbacks\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    278\u001b[0m \u001b[43m            \u001b[49m\u001b[43mtags\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtags\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    279\u001b[0m \u001b[43m            \u001b[49m\u001b[43mmetadata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmetadata\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    280\u001b[0m \u001b[43m            \u001b[49m\u001b[43mrun_name\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrun_name\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    281\u001b[0m \u001b[43m            \u001b[49m\u001b[43mrun_id\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpop\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrun_id\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    282\u001b[0m \u001b[43m            \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    283\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mgenerations[\u001b[38;5;241m0\u001b[39m][\u001b[38;5;241m0\u001b[39m],\n\u001b[0;32m    284\u001b[0m     )\u001b[38;5;241m.\u001b[39mmessage\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\language_models\\chat_models.py:714\u001b[0m, in \u001b[0;36mBaseChatModel.generate_prompt\u001b[1;34m(self, prompts, stop, callbacks, **kwargs)\u001b[0m\n\u001b[0;32m    706\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mgenerate_prompt\u001b[39m(\n\u001b[0;32m    707\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m    708\u001b[0m     prompts: List[PromptValue],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    711\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any,\n\u001b[0;32m    712\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m LLMResult:\n\u001b[0;32m    713\u001b[0m     prompt_messages \u001b[38;5;241m=\u001b[39m [p\u001b[38;5;241m.\u001b[39mto_messages() \u001b[38;5;28;01mfor\u001b[39;00m p \u001b[38;5;129;01min\u001b[39;00m prompts]\n\u001b[1;32m--> 714\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgenerate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprompt_messages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\language_models\\chat_models.py:571\u001b[0m, in \u001b[0;36mBaseChatModel.generate\u001b[1;34m(self, messages, stop, callbacks, tags, metadata, run_name, run_id, **kwargs)\u001b[0m\n\u001b[0;32m    569\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m run_managers:\n\u001b[0;32m    570\u001b[0m             run_managers[i]\u001b[38;5;241m.\u001b[39mon_llm_error(e, response\u001b[38;5;241m=\u001b[39mLLMResult(generations\u001b[38;5;241m=\u001b[39m[]))\n\u001b[1;32m--> 571\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[0;32m    572\u001b[0m flattened_outputs \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m    573\u001b[0m     LLMResult(generations\u001b[38;5;241m=\u001b[39m[res\u001b[38;5;241m.\u001b[39mgenerations], llm_output\u001b[38;5;241m=\u001b[39mres\u001b[38;5;241m.\u001b[39mllm_output)  \u001b[38;5;66;03m# type: ignore[list-item]\u001b[39;00m\n\u001b[0;32m    574\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m res \u001b[38;5;129;01min\u001b[39;00m results\n\u001b[0;32m    575\u001b[0m ]\n\u001b[0;32m    576\u001b[0m llm_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_combine_llm_outputs([res\u001b[38;5;241m.\u001b[39mllm_output \u001b[38;5;28;01mfor\u001b[39;00m res \u001b[38;5;129;01min\u001b[39;00m results])\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\language_models\\chat_models.py:561\u001b[0m, in \u001b[0;36mBaseChatModel.generate\u001b[1;34m(self, messages, stop, callbacks, tags, metadata, run_name, run_id, **kwargs)\u001b[0m\n\u001b[0;32m    558\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, m \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(messages):\n\u001b[0;32m    559\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m    560\u001b[0m         results\u001b[38;5;241m.\u001b[39mappend(\n\u001b[1;32m--> 561\u001b[0m             \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_generate_with_cache\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    562\u001b[0m \u001b[43m                \u001b[49m\u001b[43mm\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    563\u001b[0m \u001b[43m                \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    564\u001b[0m \u001b[43m                \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_managers\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrun_managers\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m    565\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    566\u001b[0m \u001b[43m            \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    567\u001b[0m         )\n\u001b[0;32m    568\u001b[0m     \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m    569\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m run_managers:\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_core\\language_models\\chat_models.py:793\u001b[0m, in \u001b[0;36mBaseChatModel._generate_with_cache\u001b[1;34m(self, messages, stop, run_manager, **kwargs)\u001b[0m\n\u001b[0;32m    791\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    792\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m inspect\u001b[38;5;241m.\u001b[39msignature(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_generate)\u001b[38;5;241m.\u001b[39mparameters\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_manager\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m--> 793\u001b[0m         result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_generate\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    794\u001b[0m \u001b[43m            \u001b[49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[0;32m    795\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    796\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    797\u001b[0m         result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_generate(messages, stop\u001b[38;5;241m=\u001b[39mstop, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\langchain_openai\\chat_models\\base.py:601\u001b[0m, in \u001b[0;36mBaseChatOpenAI._generate\u001b[1;34m(self, messages, stop, run_manager, **kwargs)\u001b[0m\n\u001b[0;32m    599\u001b[0m     generation_info \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mheaders\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mdict\u001b[39m(raw_response\u001b[38;5;241m.\u001b[39mheaders)}\n\u001b[0;32m    600\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m--> 601\u001b[0m     response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcreate\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mpayload\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    602\u001b[0m     generation_info \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m    603\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_create_chat_result(response, generation_info)\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\openai\\_utils\\_utils.py:277\u001b[0m, in \u001b[0;36mrequired_args.<locals>.inner.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    275\u001b[0m             msg \u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMissing required argument: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mquote(missing[\u001b[38;5;241m0\u001b[39m])\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    276\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(msg)\n\u001b[1;32m--> 277\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\openai\\resources\\chat\\completions.py:643\u001b[0m, in \u001b[0;36mCompletions.create\u001b[1;34m(self, messages, model, frequency_penalty, function_call, functions, logit_bias, logprobs, max_tokens, n, parallel_tool_calls, presence_penalty, response_format, seed, service_tier, stop, stream, stream_options, temperature, tool_choice, tools, top_logprobs, top_p, user, extra_headers, extra_query, extra_body, timeout)\u001b[0m\n\u001b[0;32m    609\u001b[0m \u001b[38;5;129m@required_args\u001b[39m([\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessages\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m], [\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessages\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstream\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m    610\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcreate\u001b[39m(\n\u001b[0;32m    611\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    641\u001b[0m     timeout: \u001b[38;5;28mfloat\u001b[39m \u001b[38;5;241m|\u001b[39m httpx\u001b[38;5;241m.\u001b[39mTimeout \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m|\u001b[39m NotGiven \u001b[38;5;241m=\u001b[39m NOT_GIVEN,\n\u001b[0;32m    642\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ChatCompletion \u001b[38;5;241m|\u001b[39m Stream[ChatCompletionChunk]:\n\u001b[1;32m--> 643\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_post\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    644\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/chat/completions\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m    645\u001b[0m \u001b[43m        \u001b[49m\u001b[43mbody\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmaybe_transform\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    646\u001b[0m \u001b[43m            \u001b[49m\u001b[43m{\u001b[49m\n\u001b[0;32m    647\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmessages\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mmessages\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    648\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmodel\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    649\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfrequency_penalty\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mfrequency_penalty\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    650\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfunction_call\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mfunction_call\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    651\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfunctions\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mfunctions\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    652\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mlogit_bias\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mlogit_bias\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    653\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mlogprobs\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mlogprobs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    654\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mmax_tokens\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mmax_tokens\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    655\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mn\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    656\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mparallel_tool_calls\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mparallel_tool_calls\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    657\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mpresence_penalty\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mpresence_penalty\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    658\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mresponse_format\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mresponse_format\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    659\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mseed\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mseed\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    660\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mservice_tier\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mservice_tier\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    661\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mstop\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    662\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mstream\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    663\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mstream_options\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    664\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtemperature\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mtemperature\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    665\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtool_choice\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mtool_choice\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    666\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtools\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mtools\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    667\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtop_logprobs\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mtop_logprobs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    668\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtop_p\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mtop_p\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    669\u001b[0m \u001b[43m                \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43muser\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43muser\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    670\u001b[0m \u001b[43m            \u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    671\u001b[0m \u001b[43m            \u001b[49m\u001b[43mcompletion_create_params\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCompletionCreateParams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    672\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    673\u001b[0m \u001b[43m        \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmake_request_options\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    674\u001b[0m \u001b[43m            \u001b[49m\u001b[43mextra_headers\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_headers\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mextra_query\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_query\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mextra_body\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_body\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[0;32m    675\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    676\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcast_to\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mChatCompletion\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    677\u001b[0m \u001b[43m        \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m    678\u001b[0m \u001b[43m        \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mStream\u001b[49m\u001b[43m[\u001b[49m\u001b[43mChatCompletionChunk\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    679\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\openai\\_base_client.py:1250\u001b[0m, in \u001b[0;36mSyncAPIClient.post\u001b[1;34m(self, path, cast_to, body, options, files, stream, stream_cls)\u001b[0m\n\u001b[0;32m   1236\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpost\u001b[39m(\n\u001b[0;32m   1237\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1238\u001b[0m     path: \u001b[38;5;28mstr\u001b[39m,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1245\u001b[0m     stream_cls: \u001b[38;5;28mtype\u001b[39m[_StreamT] \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1246\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ResponseT \u001b[38;5;241m|\u001b[39m _StreamT:\n\u001b[0;32m   1247\u001b[0m     opts \u001b[38;5;241m=\u001b[39m FinalRequestOptions\u001b[38;5;241m.\u001b[39mconstruct(\n\u001b[0;32m   1248\u001b[0m         method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpost\u001b[39m\u001b[38;5;124m\"\u001b[39m, url\u001b[38;5;241m=\u001b[39mpath, json_data\u001b[38;5;241m=\u001b[39mbody, files\u001b[38;5;241m=\u001b[39mto_httpx_files(files), \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions\n\u001b[0;32m   1249\u001b[0m     )\n\u001b[1;32m-> 1250\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m cast(ResponseT, \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcast_to\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mopts\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream_cls\u001b[49m\u001b[43m)\u001b[49m)\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\openai\\_base_client.py:931\u001b[0m, in \u001b[0;36mSyncAPIClient.request\u001b[1;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[0;32m    922\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrequest\u001b[39m(\n\u001b[0;32m    923\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m    924\u001b[0m     cast_to: Type[ResponseT],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    929\u001b[0m     stream_cls: \u001b[38;5;28mtype\u001b[39m[_StreamT] \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m    930\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ResponseT \u001b[38;5;241m|\u001b[39m _StreamT:\n\u001b[1;32m--> 931\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_request\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    932\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcast_to\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcast_to\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    933\u001b[0m \u001b[43m        \u001b[49m\u001b[43moptions\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43moptions\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    934\u001b[0m \u001b[43m        \u001b[49m\u001b[43mstream\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    935\u001b[0m \u001b[43m        \u001b[49m\u001b[43mstream_cls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstream_cls\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    936\u001b[0m \u001b[43m        \u001b[49m\u001b[43mremaining_retries\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mremaining_retries\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    937\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32md:\\Python\\miniconda3\\envs\\3.11_env\\Lib\\site-packages\\openai\\_base_client.py:1030\u001b[0m, in \u001b[0;36mSyncAPIClient._request\u001b[1;34m(self, cast_to, options, remaining_retries, stream, stream_cls)\u001b[0m\n\u001b[0;32m   1027\u001b[0m         err\u001b[38;5;241m.\u001b[39mresponse\u001b[38;5;241m.\u001b[39mread()\n\u001b[0;32m   1029\u001b[0m     log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRe-raising status error\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m-> 1030\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_make_status_error_from_response(err\u001b[38;5;241m.\u001b[39mresponse) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m   1032\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_process_response(\n\u001b[0;32m   1033\u001b[0m     cast_to\u001b[38;5;241m=\u001b[39mcast_to,\n\u001b[0;32m   1034\u001b[0m     options\u001b[38;5;241m=\u001b[39moptions,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1037\u001b[0m     stream_cls\u001b[38;5;241m=\u001b[39mstream_cls,\n\u001b[0;32m   1038\u001b[0m )\n",
      "\u001b[1;31mBadRequestError\u001b[0m: Error code: 400 - {'error': {'code': None, 'param': 'messages.[2].role', 'type': 'invalid_request_error', 'message': 'The role in the latest message must be `user` or `tool` - `assistant`'}}"
     ]
    }
   ],
   "source": [
    "events = graph.stream(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            HumanMessage(\n",
    "                content=\"Fetch the UK's GDP over the past 5 years,\"\n",
    "                \" then draw a line graph of it.\"\n",
    "                \" Once you code it up, finish.\"\n",
    "            )\n",
    "        ],\n",
    "    },\n",
    "    # Maximum number of steps to take in the graph\n",
    "    {\"recursion_limit\": 150},\n",
    ")\n",
    "for s in events:\n",
    "    print(s)\n",
    "    print(\"----\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "010fc36e-4116-4758-bcac-b02c7dcd405d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
